#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         __init__.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  Entry point for the product and framework
#               initialisation
#####################################################################

#####################################################################
## Python Library Imports
import sys
import os
import shutil

#####################################################################
## Zope Library Imports
from App.ImageFile import ImageFile
from Globals import DTMLFile
from App.FindHomes import ppath
from AccessControl import allow_module, allow_class, allow_type

#####################################################################
## CMF Library Imports
from Products.CMFCore import utils, permissions, DirectoryView
from Products.CMFPlone.utils import ToolInit
from App.FindHomes import ppath
from Common import getProductDirectory
import Products

#####################################################################
## Configure Python Logging 
import logging
import logging.config

ke_path = getProductDirectory() + os.sep + "logging.ini"
print "Found ke_path: %s" % ke_path
logging.config.fileConfig(ke_path)
log = logging.getLogger("KnowledgeEngine.Startup")

#####################################################################
## Knowledge Engine Library Imports
from Core import onBeforeStart, onAfterStart, getRegisteredClassInfo


def isExperimental():
    return os.environ.get('KE_EXPERIMENTAL', False) == '1'


def walk(src):
    """
        Return a list of tuples (dirpath, sub-directory-paths, files) so we can
        walk the files and sub folders in rooted at the src.
    """

    #get a list of all the stuff (files and directories) in src
    lObjects = os.listdir(src)

    #get a list of the files in src
    lFiles = [src + os.sep + f for f in lObjects if os.path.isfile(src + os.sep + f)]

    #get a list of the immediate sub directories in src
    lSubDirectories = [src + os.sep + d for d in lObjects if os.path.isdir(src + os.sep + d)]

    #create the first result
    result = [(src, lSubDirectories, lFiles)]

    #create results for each sub directory
    for lSubDirectory in lSubDirectories:
        result += walk(lSubDirectory)

    return result

#####################################################################
## BOOTSTRAP the Knowledge Engine

#define the Knowledge Engine global context
KnowledgeEngineGlobals = globals()

###############################
#Start Knowledge Engine bootstrap process
Core.onBeforeStart()

###############################
#Create the KnowledgeEngine/Cache containing the CMF skins
log.info("Commence: Creating KnowledgeEngine File Cache (for CMF skins)")

#determine the Knowledge Engine Product Path
KnowledgeEngineProductPath = getProductDirectory()

#determine the Knowledge Engine Cache path
KnowledgeEngineCachePath = KnowledgeEngineProductPath + os.sep + "Cache"

#assume cache is ok
cacheConstructionErrors = []

#ensure the cache path exists
if not os.path.exists(KnowledgeEngineCachePath):
    #try to create a cache path
    try:
        os.makedirs(KnowledgeEngineCachePath)
    except:
        cacheConstructionErrors += ["Couldn't create %s path" % KnowledgeEngineCachePath]

#ensure that the cache is empty
for lFile in os.listdir(KnowledgeEngineCachePath):
    try:
        os.remove(KnowledgeEngineCachePath + os.sep + lFile)
    except:
        cacheConstructionErrors += ["Couldn't remove %s from the Cache" % lFile]

#copy all files from 'skin' folders into the KnowledgeEngine/Cache folder
for (lRoot, lDirectories, lFiles) in walk(KnowledgeEngineProductPath):
    #is the path for a 'skin'
    if lRoot[len(lRoot)-5:] == 'skins':

        #copy all of the files into the Cache (overwriting existing files)
        for lFile in lFiles:
            try:
                if sys.platform in ("linux2", "darwin"):
                    name = lFile.split('/').pop()
                    os.symlink(lFile, KnowledgeEngineCachePath + "/" + name)
                else:                    
                    shutil.copy2(lFile, KnowledgeEngineCachePath)
            except:
                cacheConstructionErrors += ["Couldn't copy %s into the Cache" % lFile]

log.info("Complete: Created KnowledgeEngine File Cache (%d files)" % len(os.listdir(KnowledgeEngineCachePath)))

###############################
#Import Knowledge Engine Components
#(by importing them they get installed)

log.info("Commence: Importing KnowledgeEngine Plug-ins (components, editlets etc)")

#Import Assessment Infrastructure
import Assessment
import AssessmentComponentState

#Import the users and groups
from User import *

#Import Service Infrastructure
import Service
from Services import *

#Import Knowledge Engine Editlets
from Editlets import *

#Import Knowledge Engine Accessories
from Accessories import *

#Import the Model (top level component)
from Model.Model import *

#Import the Event
from Event.Event import *

#Import Knowledge Engine Components
from Components import *

#Import Knowledge Engine Actions
from Actions import *

#Import Knowledge Engine Elements
from Elements import *

#Import Knowledge Engine Reports
from Reports import *

#Import Knowledge Engine EntitySources
from EntitySources import *

log.info("Complete: Importing KnowledgeEngine Plug-ins (components, editlets etc)")

###############################
## Initialize the icons for the registered GenericObject classes
## (automatically updated when components are installed/imported)
misc_ = {}

#go through all of the registered class info
for classInfo in Core.getRegisteredClassInfo():

    #does the classInfo have an icon
    if classInfo.getClassIcon() != None:

        #add the icon to the misc_ dictionary
        misc_.update({"%s.gif" % (classInfo.getClassName(),): classInfo.getClassIcon()})

###############################
#Notify the core that all of the packages have been imported
Core.onAfterStart()

#####################################################################
## CMF Specific Initialisations

#register the general KnowledgeEngine/Cache folder (it contains all the skins)
DirectoryView.registerDirectory('Cache', KnowledgeEngineGlobals)
DirectoryView.registerDirectory('Uploads', KnowledgeEngineGlobals)

#get a reference to this python module (we need for initialising classes)
lThisModule = sys.modules[ __name__ ]

#get the portal objects that need initialising (first round)
portalObjectRegistrations = Core.getPortalObjectRegistrations()
lContentClasses = tuple([contentClass for (contentClass, classInfo, contentConstructor, fti) in portalObjectRegistrations])
lftis = tuple([fti for (contentClass, classInfo, contentConstructor, fti) in portalObjectRegistrations])

#add all of the services as classes that need to be initialised with zope
#NOTE: these are not portal object as they can only be added in the ZMI not in plone
for serviceInfo in Core.getRegisteredServiceInfo():

    #add the service class reference to the content classes for registration
    lContentClasses = lContentClasses + (serviceInfo.getClass(),)

#initialise the classes
z_bases = utils.initializeBasesPhase1(lContentClasses, lThisModule)

def initialize(productContext):
    log.info("Commence: Zope Product Initialisation")

    #add the base product classes into the product
    utils.initializeBasesPhase2(z_bases, productContext)
    
    #initialise/register each of the portal objects so they can be used in a plone portal
    for (contentClass, classInfo, contentConstructor, contentFTI) in portalObjectRegistrations:
    
        log.info("Registering Portal Object: %s" % classInfo.getClassName())
        utils.ContentInit("KnowledgeEngine: %s" % classInfo.getClassName(),
                          content_types = (contentClass,),
                          permission = permissions.AddPortalContent,
                          extra_constructors = (contentConstructor,),
                          fti = lftis
    ).initialize(productContext)

    #initialise all of the services as CMF tools
    lServiceClasses = ()
    for serviceInfo in Core.getRegisteredServiceInfo():

        #add the service class reference to the content classes for initialisation
        lServiceClasses = lServiceClasses + (serviceInfo.getClass(),)

    #initialise all of the services under the title 'KnowledgeEngine Services'
    ToolInit("KnowledgeEngine Services",
                   tools = lServiceClasses,               
                   icon = 'tool.gif').initialize(productContext)

    #declare public access to somethings so we can get at them from the python scripts
    from AccessControl import ModuleSecurityInfo, ClassSecurityInfo
    from AccessControl import allow_module, allow_class, allow_type

    allow_module('Products.KnowledgeEngine.AssessmentFilter')
    allow_module('Products.KnowledgeEngine.KERLProcessor')
    allow_module('Products.KnowledgeEngine.Utils')
    allow_module('Products.KnowledgeEngine.Utils.helpers')
    allow_module('Products.KnowledgeEngine.Utils.DisplayList')
    allow_module('Products.KnowledgeEngine.Utils.DisplayList.DisplayItem')
    allow_module('Products.KnowledgeEngine.Utils.CallbackIterator')
    
    # Plone 2.0 Compatibility hacks
    allow_module('OFS.CopySupport')
    
    log.info("Complete: Zope Product Initialisation")
    
#####################################################################
